#ifndef SCANNER_H
#define SCANNER_H
#include <string>
#include <vector>
#include <map>
#include <sstream>
#include <iostream>
#include <fstream>
#include "lex.h"
#include "tid.h"
typedef enum {
    ST_IDENT,
    ST_NUMB,
    //ST_COM,
    ST_ALE,
    ST_DELIM,
    ST_PREDELIM,
    ST_NEQ,
    ST_START,
    //ST_DIVCOM,
    ST_STRING,
    ST_EXPR_NUMB
} lexer_state;
using namespace std;
class scanner
{
    lexer_state current_state;
    vector<string> m_TS;
    TID m_tid;
    static string TW[];
    static lex_type_t words[];
    static string TD[];
    static lex_type_t delims[];
    string buff;
    char c;
    int lineno;
    ifstream fin;
    vector<char> gc_buff;
    void gc() {
        if (gc_buff.empty()) {
            c = fin.get();
            if (c == EOF) {
                fin.close();
            }
        } else {
            c = gc_buff.back();
            gc_buff.pop_back();
        }
        if (c == '\n') {
            lineno++;
        }
    }
    void ungc(char c) {
        gc_buff.push_back(c);
    }

    int TW_find(const string &p) {
        int i = 0;
        while (TW[i].size() && TW[i] != p) {
            i++;
        }
        return (TW[i].size()) ? i : -1;
    }

    int TS_find(const string &p) {
        size_t i = 0;
        for (; i < m_TS.size() && p != m_TS[i]; i++) {
            ;
        }
        return (i != m_TS.size()) ? i : -1;
    }


    int TD_find(const string &p) {
        int i = 0;
        while (TD[i].size() && TD[i] != p) {
            i++;
        }
        return (TD[i].size()) ? i : -1;
    }
public:
    scanner(const string &fname);
    lex get_lex();
    TID& get_tid() {
        return m_tid;
    }
    vector<string> & get_ts() {
        return m_TS;
    }
    /*int get_lineno() {
        return lineno;
    }*/
    string get_lineno() {
        stringstream out;
        out << lineno;
        return out.str() + " ";
    }

    string print_lex(lex &p) {

        if (p.get_type() == LEX_IDENT || p.get_type() == POLIZ_ADDR) {
            string str;
            if (p.get_type() == POLIZ_ADDR) {
                str += '&';
            }
            str += m_tid[p.get_val()].get_name();
            return str;
        }
        if (p.get_type() == POLIZ_LABEL) {
            return  '_' + sfromint(p.get_val());
        }

        if (p.get_type() == LEX_INT || p.get_type() == LEX_NUM) {
            return sfromint(p.get_val());
        }

        if (p.get_type()== POLIZ_JMP) {
                return "jmp";
        }

        if (p.get_type() == POLIZ_FJMP) {
            return "fjmp";
        }
        if (p.get_type() == POLIZ_POP) {
            return "pop";
        }

        if (p.get_type() == POLIZ_ARGSBEGIN) {
            return "argsframe:";
        }

        int i = 0;
        for (; words[i] != LEX_NULL && words[i] != p.get_type(); i++);
        if (words[i] != LEX_NULL) {
            return TW[i];
        }

        i = 0;
        for (; delims[i] != LEX_NULL && delims[i] != p.get_type(); i++);
        if (delims[i] == LEX_NULL) {
            return "";
        } else {
            return TD[i];
        }

    }
};


#endif // SCANNER_H
